package com.zhh.dataservice.service;

import com.zhh.api.model.BidInfo;
import com.zhh.api.model.IncomeRecord;
import com.zhh.api.model.ProductInfo;
import com.zhh.api.service.IncomeService;
import com.zhh.api.service.InvestService;
import com.zhh.api.service.ProductService;
import com.zhh.common.contants.FMContants;
import com.zhh.dataservice.mapper.BidInfoMapper;
import com.zhh.dataservice.mapper.FinanceAccountMapper;
import com.zhh.dataservice.mapper.IncomeRecordMapper;
import com.zhh.dataservice.mapper.ProductInfoMapper;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@DubboService(interfaceClass = IncomeService.class,version="1.0")
public class IncomeServiceImpl implements IncomeService {

    @Resource
    private ProductInfoMapper productInfoMapper;

    @Resource
    private BidInfoMapper bidInfoMapper;

    @Resource
    private IncomeRecordMapper incomeMapper;

    @Resource
    private FinanceAccountMapper accountMapper;

    //生成收益计划
    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized void generateIncomePlan() {

        //1.获取要处理的理财产品记录
        Date currentDate = new Date();
        //昨天的零点
        Date beginDate = DateUtils.truncate(DateUtils.addDays(currentDate,-1) , Calendar.DATE); //addDays()当前时间减一，truncate()把日后面的时间归零
        //今天的零点
        Date endDate = DateUtils.truncate(currentDate , Calendar.DATE);
        //找到昨天一天中到期的产品
        List<ProductInfo> productInfoList = productInfoMapper.selectFullTimeProduct(beginDate,endDate);

        BigDecimal dayRate = null; //日利率
        BigDecimal cycle = null; //周期
        BigDecimal income = null; //利息
        Date incomeDate = null; //到期时间

        //2.查询每个理财产品的多个投资记录
        for(ProductInfo product:productInfoList){
            List<BidInfo> bidList = bidInfoMapper.selectByProdId(product.getId());

            int i;
            int rows;
            //周期，新手包周期单位是天，其他的周期单位是月，所以乘30把单位变成天
            if(product.getProductType() == FMContants.PRODUCT_TYPE_XINSHOUBAO){
                i = product.getCycle();
                cycle = new BigDecimal(product.getCycle());
            }else{
                i = product.getCycle() * 30;
                cycle = new BigDecimal(product.getCycle() * 30);
            }

            //日利率 = 产品利率 / 365天 * 100%   精确到小数点后十位
            dayRate = product.getRate().divide(new BigDecimal("365"),10, RoundingMode.HALF_UP).divide(new BigDecimal("100"),10,RoundingMode.HALF_UP);

            //到期时间
            incomeDate = DateUtils.addDays(product.getProductFullTime(),i);

            //3.计算每笔投资的利息
            for(BidInfo bid:bidList){
                //利息 = 本金 * 周期 * 日利率
                income = bid.getBidMoney().multiply(cycle).multiply(dayRate);

                //4.创建收益记录，一个投资对应一个收益
                IncomeRecord incomeRecord = new IncomeRecord();
                incomeRecord.setBidId(bid.getId());
                incomeRecord.setBidMoney(bid.getBidMoney());
                incomeRecord.setIncomeDate(incomeDate);
                incomeRecord.setIncomeStatus(FMContants.INCOME_STATUS_PLAN);
                incomeRecord.setLoanId(product.getId());
                incomeRecord.setIncomeMoney(income);
                incomeRecord.setUid(bid.getUid());
                incomeMapper.insertSelective(incomeRecord);
            }
            //5.更新产品的状态
            rows = productInfoMapper.updateStatus(product.getId(),FMContants.PRODUCT_STATUS_PLAN);
            if(rows < 1 ){
                throw new RuntimeException("生成收益计划，更新产品状态为2失败");
            }
        }
    }

    //收益返还
    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized void generateIncomeBack() {
        //1.获取到期的收益记录
        Date currentDate = new Date();
        //昨天到期的
        Date expiredDate = DateUtils.truncate(DateUtils.addDays(currentDate,-1) , Calendar.DATE); //addDays()当前时间减一，truncate()把日后面的时间归零
        //获取记录
        List<IncomeRecord> incomeRecordList = incomeMapper.selectExpiredIncome(expiredDate);

        int rows;
        //2.把每个收益，返还给用户，本金 + 利息
        for(IncomeRecord incomeRecord:incomeRecordList){
            rows  = accountMapper.updateAvailableMoneyByIncomeBack(incomeRecord.getUid(),incomeRecord.getBidMoney(),incomeRecord.getIncomeMoney());
            if( rows < 1 ){
                throw new RuntimeException("收益返还，更新账号资金失败");
            }

            //3.更新收益记录的状态为 1
            incomeRecord.setIncomeStatus(FMContants.INCOME_STATUS_BACK);
            rows = incomeMapper.updateByPrimaryKey(incomeRecord);
            if( rows <1) {
                throw new RuntimeException("收益返还，更新收益记录的状态失败");
            }

        }
    }
}
